package com.ruoyi.biz.task;


import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSON;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.dataformat.xml.JacksonXmlModule;
import com.fasterxml.jackson.dataformat.xml.XmlMapper;
import com.ruoyi.biz.domain.CacheFolder;
import com.ruoyi.biz.domain.CaseInfo;
import com.ruoyi.biz.domain.TTestCaseInfo;
import com.ruoyi.biz.service.ICacheFolderService;
import com.ruoyi.biz.service.ITTestCaseInfoService;
import com.ruoyi.biz.vo.Book;
import com.ruoyi.biz.vo.CaseResult;
import com.ruoyi.biz.vo.CaseResultInfo;
import com.ruoyi.biz.vo.Project;
import com.ruoyi.system.service.ISysConfigService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.io.*;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.UUID;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

@Slf4j
@Component("parsingXMLTask")
public class ParsingXMLTask {
    //因为部署一台linux，不运行定时任务，通过判断是window的，进行任务处理
    private static final boolean isWin = System.getProperty("os.name").toLowerCase().contains("win");

    private static final boolean isLinux = System.getProperty("os.name").toLowerCase().indexOf("linux") >= 0;

    @Autowired
    private ITTestCaseInfoService itTestCaseInfoService;
    @Autowired
    private ISysConfigService iSysConfigService;
    @Autowired
    private ICacheFolderService cacheFolderService;
    /**
     * 文件夹配置key
     */
    private static final String dirConfig = "test-job:file-dir";
    /**
     * xml文件名称
     */
    private static final String xmlFileName = "Result.xml";

    /**
     * 按照每小时
     */
    public void parsingXmlHour() {
        log.info("==============读取xml文件开始【按小时开始】===================");
        parseXmlHour();
        log.info("==============读取xml文件结束【按小时开始】===================");
    }

    /**
     * 按照每天
     */
    public void parsingXmlDay() {
        log.info("==============读取xml文件开始【按天开始】===================");
        parseXmlDay();
        log.info("==============读取xml文件结束【按天开始】===================");
    }

    /**
     * 所有
     */
    public void parsingXmlAll() {
        log.info("==============读取xml文件开始【所有】===================");
        parseXmlAll();
        log.info("==============读取xml文件结束【所有】===================");
    }


    private boolean  isValidFolder(String folderName){
        String a5= "[0-9]{2}-[0-9]{2}-[0-9]{2}-[0-9]{2}-[0-9]{2}-[0-9]{2}";//yyyy-MM-dd  HH:mm
        return Pattern.compile(a5).matcher(folderName).matches();
    }
    /**
     * 读取xml，所有
     */
    private void parseXmlAll() {
      //  String fileDir = iSysConfigService.selectConfigByKey(dirConfig);
        String fileDir = "C:\\Result";
        log.info("parseXmlAll 文件目录：{}",fileDir);
        //String fileDir = "/tmp/Result";
        File[] fileList = FileUtil.ls(fileDir);
        for (File file : fileList) {
            if(!isValidFolder(file.getName())){
                continue;
            }
            if (FileUtil.isDirectory(file)) {
                System.out.println("---------------"+file.getName());
                readXml(file);
            }
        }
    }

    /**
     * 读取xml，每小时
     */
    private void parseXmlHour() {
        String fileDir = iSysConfigService.selectConfigByKey(dirConfig);
        log.info("parseXmlHour 文件目录：{}",fileDir);
       // String fileDir = "/tmp/Result";
        // 当前小时
        String currentHour = DateUtil.format(new Date(), "yy-MM-dd-HH");
        log.info("parseXmlHour 当前小时：{}",currentHour);
        File[] fileList = FileUtil.ls(fileDir);
        for (File file : fileList) {
            if(!isValidFolder(file.getName())){
                continue;
            }
            DateTime parse = DateUtil.parse(file.getName(), "yy-MM-dd-HH");
            // 减一小时
            parse.offset(DateField.HOUR, -1);
            if (FileUtil.isDirectory(file) && currentHour.equalsIgnoreCase(DateUtil.format(parse.toJdkDate(), "yy-MM-dd-HH"))) {
                readXml(file);
            }
        }
    }

    /**
     * 读取xml，每天
     */
    private void parseXmlDay() {
        String fileDir = iSysConfigService.selectConfigByKey(dirConfig);
        log.info("parseXmlDay 文件目录：{}",fileDir);
        // 当前小时
        String currentHour = DateUtil.format(new Date(), "yy-MM-dd");
        log.info("parseXmlHour 当前小时：{}",currentHour);
        File[] fileList = FileUtil.ls(fileDir);
        for (File file : fileList) {
            if(!isValidFolder(file.getName())){
                continue;
            }
            DateTime parse = DateUtil.parse(file.getName(), "yy-MM-dd");
            // 减一天
            parse.offset(DateField.DAY_OF_MONTH, -1);
            if (FileUtil.isDirectory(file) && currentHour.equalsIgnoreCase(DateUtil.format(parse.toJdkDate(), "yy-MM-dd"))) {
                readXml(file);
            }
        }
    }

    /**
     * 根据文件读取xml
     *
     * @param file
     */
    private void readXml(File file) {

        CacheFolder cacheFolder = new CacheFolder();

        cacheFolder.setFolderName(file.getName());
       List<CacheFolder> cacheFolders = cacheFolderService.selectCacheFolderList(cacheFolder);
       if(!CollectionUtils.isEmpty(cacheFolders)){
           log.warn("文件已经读取过，请不要重复操作！");
           return;
       }

        File[] files = file.listFiles();
        for (File file1 : files) {
            if (xmlFileName.equalsIgnoreCase(file1.getName())) {

                //读取xml文件
                String str = IoUtil.read(FileUtil.getInputStream(file1), Charset.defaultCharset());
                JSONObject jsonResult = JSONUtil.parseFromXml(str);
                try {
                    JSONArray jsonArray = jsonResult.getJSONObject("Result").getJSONArray("Info");
                    if(jsonArray == null || jsonArray.isEmpty()){
                        continue;
                    }
                    for (Object o : jsonArray) {
                        JSONObject obj = (JSONObject) o;
                        saveInfo(obj);
                    }

                } catch (ClassCastException e) {
                    JSONObject obj = jsonResult.getJSONObject("Result").getJSONObject("Info");
                    saveInfo(obj);
                }

            }
        }
        cacheFolder.setCreateDate(new Date());
        cacheFolderService.insertCacheFolder(cacheFolder);
    }

    /**
     * 设置测试用例
     *
     * @param obj
     */
    private void saveInfo(JSONObject obj) {
        // 合成数据
        List<TTestCaseInfo> list = new ArrayList<>();
        TTestCaseInfo tTestCaseInfo = new TTestCaseInfo();
        // 根id
        String rootId = UUID.randomUUID().toString();
        tTestCaseInfo.setRootId(rootId);
        tTestCaseInfo.setChildId(rootId);
        tTestCaseInfo.setParentId("0");
        tTestCaseInfo.setRootFlag("0");
        if (StrUtil.isNotBlank(obj.getStr("isExpanded"))) {
            tTestCaseInfo.setExpandedFlag(obj.getInt("isExpanded"));
        }
        if (StrUtil.isNotBlank(obj.getStr("Description"))) {
            tTestCaseInfo.setDescription(obj.getStr("Description"));
        }
        if (StrUtil.isNotBlank(obj.getStr("prefix"))) {
           // System.out.println(DateUtil.parse(obj.getStr("prefix")).toJdkDate());
            tTestCaseInfo.setPrefix(DateUtil.parse(obj.getStr("prefix")));
        }
        if (StrUtil.isNotBlank(obj.getStr("type"))) {
            tTestCaseInfo.setType(obj.getStr("type"));
        }
        if (StrUtil.isNotBlank(obj.getStr("suffix"))) {
            tTestCaseInfo.setSuffix(obj.getStr("suffix"));
        }
        if (StrUtil.isNotBlank(obj.getStr("version"))) {
            tTestCaseInfo.setVersion(obj.getStr("version"));
        }
        if (StrUtil.isNotBlank(obj.getStr("ResultFolder"))) {
            tTestCaseInfo.setResultFolder(obj.getStr("ResultFolder"));
        }
        list.add(tTestCaseInfo);
        if (obj.containsKey("Info")) {
            try {
                for (Object obj2 : obj.getJSONArray("Info")) {
                    getChildData(list, (JSONObject) obj2, rootId, rootId);
                }
            } catch (ClassCastException ex) {
                getChildData(list, obj.getJSONObject("Info"), rootId, rootId);
            }
        }
        log.info("内容 -=- {}", list);
        log.info("内容长度 -=- {}", list.size());
        list.stream().forEach(tTestCaseInfo2 -> {
            // 添加
           // System.out.println(list.toString());
           itTestCaseInfoService.insertTTestCaseInfo(tTestCaseInfo2);
        });
        setType(list, rootId);
        setVersion(list, rootId);
    }

    /**
     * 设置type
     *
     * @param list
     * @param rootId
     */
    private void setType(List<TTestCaseInfo> list, String rootId) {
        List<TTestCaseInfo> collect = list.stream().filter(tTestCaseInfo1 -> tTestCaseInfo1.getRootId().equalsIgnoreCase(rootId) && "显示控制器类型DUTType".equalsIgnoreCase(tTestCaseInfo1.getDescription())).collect(Collectors.toList());
        if (CollUtil.isNotEmpty(collect)) {
            TTestCaseInfo tTestCaseInfo4 = collect.get(0);
            List<TTestCaseInfo> collect2 = list.stream().filter(tTestCaseInfo1 -> tTestCaseInfo1.getParentId().equalsIgnoreCase(tTestCaseInfo4.getChildId())).collect(Collectors.toList());
            if (CollUtil.isNotEmpty(collect2)) {
                TTestCaseInfo info = collect2.get(0);
                String description = info.getDescription();
                TTestCaseInfo infoByChildId = itTestCaseInfoService.getInfoByChildId(info.getRootId());
                infoByChildId.setType(description);
                itTestCaseInfoService.updateTTestCaseInfo(infoByChildId);
            }
        }
    }

    /**
     * 设置version
     *
     * @param list
     * @param rootId
     */
    private void setVersion(List<TTestCaseInfo> list, String rootId) {
        List<TTestCaseInfo> collect3 = list.stream().filter(tTestCaseInfo1 -> tTestCaseInfo1.getRootId().equalsIgnoreCase(rootId) && "显示控制器软件版本DUTVersion".equalsIgnoreCase(tTestCaseInfo1.getDescription())).collect(Collectors.toList());
        if (CollUtil.isNotEmpty(collect3)) {
            TTestCaseInfo tTestCaseInfo5 = collect3.get(0);
            List<TTestCaseInfo> collect4 = list.stream().filter(tTestCaseInfo1 -> tTestCaseInfo1.getParentId().equalsIgnoreCase(tTestCaseInfo5.getChildId())).collect(Collectors.toList());
            if (CollUtil.isNotEmpty(collect4)) {
                TTestCaseInfo info2 = collect4.get(0);
                String description2 = info2.getDescription();
                TTestCaseInfo infoByChildId2 = itTestCaseInfoService.getInfoByChildId(info2.getRootId());
                infoByChildId2.setVersion(description2);
                itTestCaseInfoService.updateTTestCaseInfo(infoByChildId2);
            }
        }
    }

    /**
     * 递归处理数据
     *
     * @param list
     * @param obj2
     * @param rootId
     * @param parentId
     */
    private void getChildData(List<TTestCaseInfo> list, JSONObject obj2, String rootId, String parentId) {
        JSONObject obj = obj2;
        TTestCaseInfo tTestCaseInfo = new TTestCaseInfo();
        String s = UUID.randomUUID().toString();
        tTestCaseInfo.setRootId(rootId);
        tTestCaseInfo.setParentId(parentId);
        tTestCaseInfo.setChildId(s);
        if (StrUtil.isNotBlank(obj.getStr("isExpanded"))) {
            tTestCaseInfo.setExpandedFlag(obj.getInt("isExpanded"));
        }
        if (StrUtil.isNotBlank(obj.getStr("Description"))) {
            if(obj.getStr("Description").length() < 255){
                tTestCaseInfo.setDescription(obj.getStr("Description"));
            }else {
                tTestCaseInfo.setDescription(obj.getStr("Description").substring(0,254));
            }

        }
        if (StrUtil.isNotBlank(obj.getStr("prefix"))) {
            tTestCaseInfo.setPrefix(DateUtil.parse(obj.getStr("prefix")).toJdkDate());
        }
        if (StrUtil.isNotBlank(obj.getStr("type"))) {
            tTestCaseInfo.setType(obj.getStr("type"));
        }
        if (StrUtil.isNotBlank(obj.getStr("suffix"))) {
            tTestCaseInfo.setSuffix(obj.getStr("suffix"));
        }
        if (StrUtil.isNotBlank(obj.getStr("version"))) {
            tTestCaseInfo.setVersion(obj.getStr("version"));
        }
//        if (StrUtil.isNotBlank(obj.getStr("ResultFolder"))) {
//            tTestCaseInfo.setResultFolder(obj.getStr("ResultFolder"));
//        }
        list.add(tTestCaseInfo);
        if (obj.containsKey("Info")) {
            getChildData(list, obj.getJSONObject("Info"), rootId, s);
        }
    }

    public static void main(String[] args) {
        ParsingXMLTask parsingXMLTask = new ParsingXMLTask();
        parsingXMLTask.parseXmlAll();
//        String s = DateUtil.format(new Date(), "yy-MM-dd-HH");
//        System.out.println(s);
//
//        DateTime parse = DateUtil.parse("21-03-01-14-39-03", "yy-MM-dd-HH");
//        parse.offset(DateField.DAY_OF_MONTH, -1);
//        System.out.println(DateUtil.format(parse.toJdkDate(), "yy-MM-dd-HH"));

    }
}
//1. 为了方便定义两个定时器， 1--1个小时读取一次目录，获取前一小时内的文件夹 ，2 --1天读取一次目录，获取昨天内的文件夹
//2. 解析resultxml，一个result里有多个case（第一级info），每一个case下的第一个info和第二个info如果包含字段（DUTType, DUTVersion），那么这个就是当前case
//   的type，和version
//3. 解析入库
//4. 前台数据展示。主页显示所有case的第一级，点击详情查看case的tree型结构
//5. 前台汇总展示，根据开始时间和结束时间显示测试用例总数，测试用例执行个数，测试用例失败个数（只计算第一级），默认汇总所有
//6. 导出，按照excel进行导出